#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
应用启动配置 - 优化版本

包含：
1. 后台任务启动
2. WebSocket连接管理
3. Redis连接检查
4. 数据库连接池配置
"""

import asyncio
import signal
import sys
from contextlib import asynccontextmanager

from fastapi import FastAPI

from app.service.background_tasks import get_background_service
from app.common.websocket_manager import get_websocket_manager
from common.logger import create_logger
from common.redis import get_redis_service
# from common.database import DatabaseManager  # 已移除：FastAPI不再直接管理OutboxRelay
# from mqtt.consumer.domain.relay import RedisRelay  # 已移除
# from mqtt.consumer.worker.outbox_relay import OutboxRelayThread  # 已移除
# from mqtt.consumer.repository.outbox_repository import set_outbox_relay_instance  # 已移除

logger = create_logger(__name__)


class StartupManager:
    """启动管理器"""

    def __init__(self):
        self.background_service = get_background_service()
        self.redis_service = get_redis_service()
        self.shutdown_event = asyncio.Event()
        self.outbox_relay_thread = None  # OutboxRelay线程

    async def startup(self):
        """应用启动时执行"""
        logger.info("开始启动数据大屏服务...")

        try:
            # 1. 检查Redis连接
            await self._check_redis_connection()

            # 2. 不再启动OutboxRelay线程（由MQTT消费者负责）
            # await self._start_outbox_relay()  # 已移除：避免与MQTT消费者的OutboxRelay冲突

            # 3. 启动后台任务
            await self._start_background_tasks()

            # 4. 设置信号处理
            self._setup_signal_handlers()

            logger.info("数据大屏服务启动完成")

        except Exception as e:
            logger.error(f"启动失败: {e}")
            raise

    async def shutdown(self):
        """应用关闭时执行"""
        logger.info("开始关闭数据大屏服务...")

        try:
            # 1. 不再停止OutboxRelay线程（由MQTT消费者管理）
            # await self._stop_outbox_relay()  # 已移除：OutboxRelay由MQTT消费者管理

            # 2. 停止后台任务
            await self._stop_background_tasks()

            # 3. 关闭WebSocket连接
            await self._close_websocket_connections()

            # 4. 设置关闭事件
            self.shutdown_event.set()

            logger.info("数据大屏服务关闭完成")

        except Exception as e:
            logger.error(f"关闭过程中出现错误: {e}")

    async def _check_redis_connection(self):
        """检查Redis连接"""
        try:
            if self.redis_service.is_available():
                logger.info("Redis连接正常")
            else:
                logger.warning("Redis连接失败，将使用数据库降级模式")
        except Exception as e:
            logger.warning(f"Redis连接检查失败: {e}，将使用数据库降级模式")

    # async def _start_outbox_relay(self):
    #     """启动OutboxRelay线程（已移除：由MQTT消费者负责）"""
    #     try:
    #         # 初始化数据库连接
    #         db = DatabaseManager()
    #
    #         # 初始化事件中继
    #         relay = RedisRelay(self.redis_service.client if self.redis_service.is_available() else None)
    #
    #         # 启动 Outbox 中继线程
    #         self.outbox_relay_thread = OutboxRelayThread(db, relay, interval=0.5)
    #
    #         # 设置全局OutboxRelay实例
    #         set_outbox_relay_instance(self.outbox_relay_thread)
    #
    #         self.outbox_relay_thread.start()
    #         logger.info("FastAPI Outbox事件中继线程已启动")
    #
    #     except Exception as e:
    #         logger.error(f"启动OutboxRelay线程失败: {e}")
    #         raise

    # async def _stop_outbox_relay(self):
    #     """停止OutboxRelay线程（已移除：由MQTT消费者管理）"""
    #     try:
    #         if self.outbox_relay_thread:
    #             self.outbox_relay_thread.stop()
    #             # 等待线程结束（最多5秒）
    #             self.outbox_relay_thread.join(timeout=5)
    #             logger.info("FastAPI Outbox中继线程已停止")
    #     except Exception as e:
    #         logger.error(f"停止OutboxRelay线程失败: {e}")

    async def _start_background_tasks(self):
        """启动后台任务"""
        try:
            await self.background_service.start_background_tasks()
            logger.info("后台任务启动成功")
        except Exception as e:
            logger.error(f"启动后台任务失败: {e}")
            raise

    async def _stop_background_tasks(self):
        """停止后台任务"""
        try:
            await self.background_service.stop_background_tasks()
            logger.info("后台任务停止成功")
        except Exception as e:
            logger.error(f"停止后台任务失败: {e}")

    async def _close_websocket_connections(self):
        """关闭所有WebSocket连接"""
        try:
            # 向所有连接发送关闭通知
            websocket_manager = get_websocket_manager()
            if websocket_manager.active_connections:
                close_message = {
                    "type": "server_shutdown",
                    "message": "服务器正在关闭，连接将断开"
                }
                await websocket_manager.broadcast(close_message)

                # 等待一秒让客户端处理消息
                await asyncio.sleep(1)

                # 强制关闭所有连接
                for websocket in list(websocket_manager.active_connections):
                    try:
                        await websocket.close(code=1001, reason="服务器关闭")
                    except:
                        pass
                    websocket_manager._remove_connection(websocket)

                logger.info(f"已关闭所有WebSocket连接")
        except Exception as e:
            logger.error(f"关闭WebSocket连接失败: {e}")

    def _setup_signal_handlers(self):
        """设置信号处理器"""
        def signal_handler(signum, frame):
            logger.info(f"收到信号 {signum}，开始优雅关闭...")
            asyncio.create_task(self.shutdown())

        # 注册信号处理器
        signal.signal(signal.SIGINT, signal_handler)
        signal.signal(signal.SIGTERM, signal_handler)


# 全局启动管理器
startup_manager = StartupManager()


@asynccontextmanager
async def lifespan(app: FastAPI):
    """FastAPI生命周期管理"""
    # 启动
    await startup_manager.startup()

    try:
        yield
    finally:
        # 关闭
        await startup_manager.shutdown()


def get_lifespan_manager():
    """获取生命周期管理器"""
    return lifespan


# 便捷函数
async def startup_dashboard_services():
    """启动数据大屏服务的便捷函数"""
    await startup_manager.startup()


async def shutdown_dashboard_services():
    """关闭数据大屏服务的便捷函数"""
    await startup_manager.shutdown()


def get_startup_manager() -> StartupManager:
    """获取启动管理器实例"""
    return startup_manager